package org.bonorsoft.modules.dingding.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.bonorsoft.common.aspect.annotation.AutoLog;
import org.bonorsoft.common.constant.CommonConstant;
import org.bonorsoft.common.constant.DingdingConstant;
import org.bonorsoft.common.constant.EducationConstant;
import org.bonorsoft.common.dingapi.DingdingCallback;
import org.bonorsoft.common.dingapi.DingdingDepart;
import org.bonorsoft.common.dingapi.DingdingUser;
import org.bonorsoft.common.dingapi.dingtalk.aes.DingTalkEncryptor;
import org.bonorsoft.common.dingapi.dingtalk.aes.Utils;

import org.bonorsoft.modules.dingding.entity.SysDepart;
import org.bonorsoft.modules.dingding.entity.SysDingUser;
import org.bonorsoft.modules.dingding.service.ISysDepartService;
import org.bonorsoft.modules.dingding.service.ISysDingUserService;
import org.bonorsoft.modules.dingding.service.ISysRoleService;
import org.bonorsoft.modules.dingding.service.ISysUserRoleService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController
public class DingCallBack {

    @Autowired
    private ISysDepartService sysDepartService;

    @Autowired
    private ISysRoleService sysRoleService;

    @Autowired
    private ISysDingUserService sysUserService;

    @Autowired
    private ISysUserRoleService sysUserRoleService;

    private static final Logger bizLogger = LoggerFactory.getLogger("BIZ_CALLBACKCONTROLLER");
    private static final Logger mainLogger = LoggerFactory.getLogger(DingdingCallback.class);

    /**
     * 相应钉钉回调时的值
     */
    private static final String CALLBACK_RESPONSE_SUCCESS = "success";

    @AutoLog(value = "钉钉通讯录-部门/人员/角色变动")
    @RequestMapping(value = "/callback", method = RequestMethod.POST)
    @ResponseBody
    public Map<String, String> callback(@RequestParam(value = "signature", required = false) String signature,
                                        @RequestParam(value = "timestamp", required = false) String timestamp,
                                        @RequestParam(value = "nonce", required = false) String nonce,
                                        @RequestBody(required = false) JSONObject json) {
        String params = " signature:"+signature + " timestamp:"+timestamp +" nonce:"+nonce+" json:"+json;
        try {
            DingTalkEncryptor dingTalkEncryptor = new DingTalkEncryptor(EducationConstant.TOKEN, EducationConstant.ENCODING_AES_KEY,
                    EducationConstant.CORP_ID);

            //从post请求的body中获取回调信息的加密数据进行解密处理
            String encryptMsg = json.getString("encrypt");
            String plainText = dingTalkEncryptor.getDecryptMsg(signature, timestamp, nonce, encryptMsg);
            JSONObject obj = JSON.parseObject(plainText);

            //根据回调数据类型做不同的业务处理
            String eventType = obj.getString("EventType");
            if (CommonConstant.ORG_DEPT_CREAT.equals(eventType)) {
                bizLogger.info("通讯录企业部门创建: " + plainText);
                //todo: 通讯录企业部门创建
                List<Integer> deptId = JSONArray.parseArray(obj.getString("DeptId"), Integer.class);
                sysDepartService.addOrUpdateDepart(deptId);
            } else if (CommonConstant.ORG_DEPT_MODIFY.equals(eventType)) {
                bizLogger.info("通讯录企业部门修改: " + plainText);
                //todo: 通讯录企业部门修改
                List<Integer> deptId = JSONArray.parseArray(obj.getString("DeptId"), Integer.class);
                sysDepartService.addOrUpdateDepart(deptId);
            } else if (CommonConstant.ORG_DEPT_REMOVE.equals(eventType)) {
                bizLogger.info("通讯录企业部门删除: " + plainText);
                //todo: 通讯录企业部门删除
                List<Integer> deptId = JSONArray.parseArray(obj.getString("DeptId"), Integer.class);
                sysDepartService.deleteDepart(deptId);
            } else if (CommonConstant.USER_ADD_ORG.equals(eventType)) {
                bizLogger.info("通讯录用户增加: " + plainText);
                //todo: 通讯录用户增加
                // 注释原因：用户添加的时候会同时执行更改的回调函数，如果两个都执行，数据库会存入两条用户信息
                //List<String> userList = JSONArray.parseArray(obj.getString("UserId"), String.class);
                //String createBy = obj.getString("OptStaffId");
                //sysUserService.addUser(userList,CommonConstant.USER_ADD_ORG,createBy);
            } else if (CommonConstant.USER_MODIFY_ORG.equals(eventType)) {
                bizLogger.info("通讯录用户更改: " + plainText);
                //todo: 通讯录用户更改
                List<String> userList = JSONArray.parseArray(obj.getString("UserId"), String.class);
                String userId = obj.getString("OptStaffId");
                sysUserService.addOrUpdateUser(userList, userId);
            } else if (CommonConstant.USER_LEAVE_ORG.equals(eventType)) {
                bizLogger.info("通讯录用户离职: " + plainText);
                //todo: 通讯录用户离职
                List<String> userList = JSONArray.parseArray(obj.getString("UserId"), String.class);
                sysUserService.deleteUser(userList);
            } else if (CommonConstant.USER_ACTIVE_ORG.equals(eventType)) {
                bizLogger.info("加入企业后用户激活: " + plainText);
                //todo: 加入企业后用户激活
                List<String> UserId = JSONArray.parseArray(obj.getString("UserId"), String.class);
                sysUserService.updateUser(UserId);
            } else if (CommonConstant.ORG_ADMIN_ADD.equals(eventType)) {
                bizLogger.info("通讯录用户被设为管理员: " + plainText);
                //todo: 通讯录用户被设为管理员
                List<String> UserId = JSONArray.parseArray(obj.getString("UserId"), String.class);
                sysUserService.updateUser(UserId);
            } else if (CommonConstant.ORG_ADMIN_REMOVE.equals(eventType)) {
                bizLogger.info("通讯录用户被取消设置管理员: " + plainText);
                //todo: 通讯录用户被取消设置管理员
                List<String> UserId = JSONArray.parseArray(obj.getString("UserId"), String.class);
                sysUserService.updateUser(UserId);
            } else if (CommonConstant.LABEL_USER_CHANGE.equals(eventType)) {
                bizLogger.info("员工角色信息发生变更: " + plainText);
                //todo: 员工角色信息发生变更
                List<String> UserIdList = JSONArray.parseArray(obj.getString("UserIdList"), String.class);
                List<Integer> LabelIdList = JSONArray.parseArray(obj.getString("LabelIdList"), Integer.class);
                String type = obj.getString("action");
                if(CommonConstant.LABEL_USER_CHANGE_ADD.equals(type)){
                    sysUserRoleService.addUserRole(UserIdList, LabelIdList);
                } else if(CommonConstant.LABEL_USER_CHANGE_DELETE.equals(type)){
                    sysUserRoleService.deleteUserRole(UserIdList, LabelIdList);
                }
            } else if (CommonConstant.LABEL_CONF_ADD.equals(eventType)) {
                bizLogger.info("增加角色或者角色组: " + plainText);
                //todo: 增加角色或者角色组
                List<Integer> labelIdList = JSONArray.parseArray(obj.getString("LabelIdList"), Integer.class);
                sysRoleService.addRole(labelIdList);
            } else if (CommonConstant.LABEL_CONF_DEL.equals(eventType)) {
                bizLogger.info("删除角色或者角色组: " + plainText);
                //todo: 删除角色或者角色组
                List<Integer> labelIdList = JSONArray.parseArray(obj.getString("LabelIdList"), Integer.class);
                sysRoleService.deleteRole(labelIdList);
            } else if (CommonConstant.LABEL_CONF_MODIFY.equals(eventType)) {
                bizLogger.info("修改角色或者角色组: " + plainText);
                //todo: 修改角色或者角色组
                List<Integer> labelIdList = JSONArray.parseArray(obj.getString("LabelIdList"), Integer.class);
                sysRoleService.addRole(labelIdList);
            } else if (CommonConstant.ORG_CHANGE.equals(eventType)){
                bizLogger.info("企业信息发生变更: " + plainText);
                //todo: 企业信息发生变更
            } else if (CommonConstant.ORG_REMOVE.equals(eventType)){
                bizLogger.info("企业被解散: " + plainText);
                //todo: 企业被解散
            } else {
                // 其他类型事件处理
            }

            // 返回success的加密信息表示回调处理成功
            return dingTalkEncryptor.getEncryptedMap(CALLBACK_RESPONSE_SUCCESS, System.currentTimeMillis(), Utils.getRandomStr(8));
        } catch (Exception e) {
            //失败的情况，应用的开发者应该通过告警感知，并干预修复
            mainLogger.error("process callback failed！"+params,e);
            return null;
        }

    }

    /** 功能描述:获取钉钉组织架构下的所有部门，已经部门下的所有用户信息
     *
     * @vison: 1.0.0
     * @Author: WilliamYe
     * @Date: 2020/11/18 16:16
     */
    private static void synchronousInformation(){
        String result = DingdingDepart.getDepartmentListSub(DingdingConstant.PARENT_ID);
        List<SysDepart> departList = JSONArray.parseArray(result, SysDepart.class);
        removeSchool(departList);
        List<SysDepart> list = new ArrayList<>(departList);
        getChildDepart(departList,list);
        List<SysDingUser> userByDepartList = getUserByDepartList(list);
        System.out.println(list.size());
        System.out.println(userByDepartList.size());
    }

    /** 功能描述:根据全部部门列表获取该部门下所有用户（并去重）
     * 此操作把后面的两个userid相同的都给剔除了。若两个userid一样，其他数据不同的话，留下的数据是靠前的数据，剔除的是靠后的数据。
     *
     * @vison: 1.0.0
     * @Author: WilliamYe
     * @Date: 2020/11/18 16:01
     * @return
     */
    private static List<SysDingUser> getUserByDepartList(List<SysDepart> list) {
        List<SysDingUser> sysDingUsers = new ArrayList<>();
        List<SysDingUser> finalSysDingUsers = sysDingUsers;
        list.forEach(item->{
            String userList = DingdingUser.getUserList(item.getDeptId(), 400L, 100L);
            JSONObject obj = JSON.parseObject(userList);
            List<SysDingUser> userLists = JSONArray.parseArray(obj.getString("list"), SysDingUser.class);
            if(userLists.size() != 0){
                userLists.forEach(item_user -> item_user.setDeptIdList(item_user.getDeptIdList()
                            .replace("[","")
                            .replace("]",""))
                );
                finalSysDingUsers.addAll(userLists);
            }
        });
        sysDingUsers = sysDingUsers.stream().collect(Collectors.collectingAndThen(Collectors.toCollection(() -> new TreeSet<>(Comparator.comparing(SysDingUser :: getUserid))), ArrayList::new));
        return sysDingUsers;
    }

    /** 功能描述:获取子部门
     *
     * @vison: 1.0.0
     * @Author: WilliamYe
     * @Date: 2020/11/18 15:49
     * @param list --全部部门
     * @param departList -- 某个部门下的全部子部门
     */
    private static void getChildDepart(List<SysDepart> departList, List<SysDepart> list){
        departList.forEach(item->{
            String child = DingdingDepart.getDepartmentListSub(item.getDeptId());
            List<SysDepart> syDeparts = JSONArray.parseArray(child, SysDepart.class);
            if (syDeparts.size()!=0){
                list.addAll(syDeparts);
                getChildDepart(syDeparts,list);
            }
        });
    }

    /** 功能描述: 去除家校通讯录的部门
     *
     * @vison: 1.0.0
     * @Author: WilliamYe
     * @Date: 2020/11/18 15:23
     */
    private static void removeSchool(List<SysDepart> departList) {
        departList.removeIf(depart -> depart.getDeptId().equals(DingdingConstant.SCHOOL_TAG));
    }

    public static void main(String[] args){
        synchronousInformation();
    }

}
